using System;
using System.Xml;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace NGNntpPlugIn
{
	/// <summary>
	/// Summary description for NntpServer.
	/// </summary>
	public class NntpServer
	{
		#region Private Members

		private string m_server = "";
		private NntpNewsgroupCollection m_newsgroups;
		private string m_userName = "";
		private string m_password = "";

		// private key members
		private static byte[] keyb = {112,57,9,27,192,15,92,39,75,216,43,25,9,76,49,57,4,145,62,181,246,0,189,41,205,60,178,41,62,47,254,61};
		private static byte[] ivb = {2,84,6,50,48,162,50,61,240,161,4,79,216,80,46,148};

	
		#endregion

		#region Public Properties

		public NntpServer(XmlNode outlineNode, bool addNewsgroup)
		{
			m_newsgroups = new NntpNewsgroupCollection();

			// get the xml url
			string xmlurl = outlineNode.Attributes["xmlUrl"].Value;

			// create a regular expression to parse the url
			Regex rxLink = new Regex(@"(?<type>nntp|news)://(?<server>.*)/(?<newsgroup>.*)", RegexOptions.Compiled);

			Match match = rxLink.Match(xmlurl);
			if(match.Groups.Count > 0)
			{
				// matches were found
				m_server = match.Groups["server"].Value;
				if(addNewsgroup)
					m_newsgroups.Add(new NntpNewsgroup(match.Groups["newsgroup"].Value, false));
			}

			// get the username and password
			foreach(XmlNode att in outlineNode.Attributes)
			{
				if(att.Name.ToLower() == "ng:username")
					m_userName = att.Value;
				if(att.Name.ToLower() == "ng:passwordenc")
					m_password = att.Value;
			}
		}

		public NntpServer(string server, string newsgroup, string userName, string password)
		{
			m_server = server;
			m_userName = userName;
			m_password = password;

			m_newsgroups = new NntpNewsgroupCollection();
			string[] ngs = newsgroup.Split(',');
			foreach(string ng in ngs)
			{
				m_newsgroups.Add(new NntpNewsgroup(ng, true));
			}
		}

		public string Server
		{
			get { return m_server; }
		}

		public NntpNewsgroupCollection Newsgroups
		{
			get { return m_newsgroups; }
		}

		public string UserName
		{
			get { return m_userName; }
		}

		public string Password
		{
			get { return DecryptString(m_password); }
		}

		public bool Authenticate
		{
			get { return (m_userName != "" && m_password != ""); }
		}

		#endregion

		#region Private Methods

		internal static string DecryptString(string src) 
		{
			byte[] p = Convert.FromBase64String(src);
			byte[] initialText = new Byte[p.Length];

			RijndaelManaged rv = new RijndaelManaged();
			MemoryStream ms = new MemoryStream(p);
			CryptoStream cs = new CryptoStream(ms, rv.CreateDecryptor(keyb, ivb), CryptoStreamMode.Read);

			int read = 0;
			try 
			{
				read = cs.Read(initialText, 0, initialText.Length);
			}
			finally 
			{
				ms.Close();
				cs.Close();
			}

			ASCIIEncoding enc = new ASCIIEncoding();
			return enc.GetString(initialText, 0, read); 
		}


		#endregion

		#region Overidden Methods

		public override string ToString()
		{
			return this.Server;
		}


		#endregion

		#region Public Methods

		public bool IsNewsgroupSelected()
		{
			bool selected = false;

			foreach(NntpNewsgroup ng in this.Newsgroups)
			{
				if(ng.IsSelected)
				{
					selected = true;
					break;
				}
			}

			return selected;
		}

		#endregion
	}
}
